# Licensed under the GNU Lesser General Public License, version 2.1 (LGPL-2.1)
# Full text is available at:
#
#    http://www.gnu.org/licenses/lgpl-2.1.txt
#
# This file is part of cyg-get.
#
#    cyg-get is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Lesser General Public License as
#    published by the Free Software Foundation, either version 2.1 of
#    the License, or (at your option) any later version.
#
#    cyg-get is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU Lesser General Public
#    License along with cyg-get.
#
#    If not, see <http://www.gnu.org/licenses/>.

package Cygwin::Source;

use strict;
use File::Temp;

use Cygwin::Package;

sub new {
    my $class = shift;
    my $this = bless {}, $class;
    
    $this->{sources} = [];
    $this->{packages} = {};

    load($this) unless shift();
    
    return $this;
}

sub load {
    my $this = shift;
    
    my $var = "/var/lib/cyg-get/";
    my $lists = $var . "lists";
    
    my $pkg;
    my $pkg_name;
    
    my $sect;
    my $desc;
    
    my $source;
    
    foreach my $list (glob($lists . "/*list")) {
        open( FH, "<", $list );
        $source = <FH>;
        
        $source =~ m{# Source => (.*)\s*};
        $source = $1;
        
        if( $list =~ m{.*/([^/.]+).list} ) {
            push @{$this->{sources}}, $source;
        }
        
        while( my $line = <FH> ) {
            if( $line =~ m{^@ ([^ ]+)$} ) {
                $pkg_name = $1;
                chomp $pkg_name;
                
                $pkg = $this->{packages}{$pkg_name};
                $pkg = Cygwin::Package->new($pkg_name) unless defined($pkg);
                
                $line = <FH>;
                while( !($line =~ m{^$}) ) {
                    SWITCH: {
                        if( $line =~ m{^([sl]desc): (.*)} ) {
                            $sect = $1;
                            $desc = $2;
                            while( !($desc =~ m{^\s*".*"\s*$}) ) {
                                $line = <FH>;
                                chomp $line;
                                $desc = $desc . " " . $line;
                            }
                            $desc =~ m{^\s*"(.*)"\s*$};
                            $pkg->{$sect} = $1;
                            last SWITCH;
                        }
                        if( $line =~ m{^(version): (.*)} ) {
                            $sect = $1;
                            $desc = $2;
                            $pkg->{ver} = $desc;
                            last SWITCH;
                        }
                        if( $line =~ m{^(category): (.*)} ) {
                            $sect = $1;
                            $desc = $2;
                            push @{$pkg->{categories}}, split(/ /, $desc);
                            last SWITCH;
                        }
                        if( $line =~ m{^(requires): (.*)} ) {
                            $sect = $1;
                            $desc = $2;
                            push @{$pkg->{requires}}, split(/ /, $desc);
                            last SWITCH;
                        }
                        if( $line =~ m{^(install|source): ([^ ]+)} ) {
                            $sect = $1;
                            $desc = $2;
                            push @{$pkg->{$sect}}, $desc;
                            last SWITCH;
                        }
                        # print $line unless $line =~ m{\[(?:prev|test)\]};
                    }
                    $line = <FH>;
                    last unless defined($line);
                }
                
                @{$pkg->{categories}} = &sortAndRemoveDuplicates($pkg->{categories});
                @{$pkg->{requires}}   = &sortAndRemoveDuplicates($pkg->{requires});
                @{$pkg->{install}}    = &sortAndRemoveDuplicates($pkg->{install}, "reverse");
                @{$pkg->{source}}     = &sortAndRemoveDuplicates($pkg->{source}, "reverse");
                
                $this->{packages}{$pkg_name} = $pkg;
            }
        }
        close(FH);
    }
}

sub sortAndRemoveDuplicates {
    my $array = shift;
    my $reverse = shift;
    
    my %t = ();
    foreach my $val (@{$array}) {
        $t{$val} = 1;
    }
    
    if( defined($reverse) ) {
        @{$array} = sort {lc($b) cmp lc($a)} keys %t;
    } else {
        @{$array} = sort {lc($a) cmp lc($b)} keys %t;
    }
    
    return @{$array};
}

sub update {
    my $this = shift;
    my $path = shift;
    
    if( !defined($path) ) {
        $path = "/etc/setup/setup.rc";
    }
    
    my $var = "/var/lib/cyg-get/";
    my $lists = $var . "lists";
    #my $cache = $var . "cache";
    
    open( FH, "<", $path );
    while( my $line = <FH> ) {
        if( $line eq "last-mirror\n" ) {
            $line = <FH>;
            while( $line =~ m{^\s+} ) {
                chomp $line;
                $line =~ m{\s*([^ ]+)\s*};
                push @{$this->{sources}}, $1;
                $line = <FH>;
            }
        }
    }
    close(FH);
    
    foreach my $source (@{$this->{sources}}) {
        $source =~ m{.*?([^.]+)\.[^.]+/};
        my $sname = $1;
        
        print "Updating $sname...\n";
        
        system("lwp-download",
               $source . "setup.bz2",
               "$lists/$sname.list.bz2");
        
        if( -r "$lists/$sname.list.bz2" ) {
            my $list = "$lists/$sname.list";
            open( FH, ">", $list );
            my $oldfh = select FH;
            
            $|++;
            print "# Source => $source\n";
            print "\n";
            
            close(FH);
            select $oldfh;
            
            system("bzip2 -vdc '$lists/$sname.list.bz2' >> $list");
        }
    }
}

sub find {
    my $this = shift;
    my @results = ();
    
    foreach my $regex (@_) {
        foreach my $key (sort(keys %{$this->{packages}})) {
            if( $key =~ m{$regex} ) {
                push @results, $this->{packages}{$key};
            }
        }
    }
    
    return @results;
}
1;